using System;
using System.DHTML;
using System.Gadgets;
using ScriptFX;
using ScriptFX.UI;

namespace MythtvGadget
{

    public class GadgetScriptlet
    {
        int timer = 0;
        private bool CallInProgress = false;

        private bool _flyoutVisible;

        static GadgetScriptlet()
        {
            if (Document.Body.ID == "gadget")
            {
                Application.Current.Run(typeof(GadgetScriptlet), null);
            }
        }

        private GadgetScriptlet()
        {
            Gadget.SettingsUI = "Settings.htm";
			
            Gadget.OnDock = OnDock;
            Gadget.OnUndock = OnUndock;

            Gadget.Flyout.File = "Flyout.htm";
            Gadget.Flyout.OnShow = OnFlyoutShow;
            Gadget.Flyout.OnHide = OnFlyoutHide;

            Gadget.OnSettingsClosed = OnSettingsClosed;
            
            UpdateDockedState();

#if DEBUG
            if (String.IsNullOrEmpty(Settings.StatusUrl))
            {
                Settings.StatusUrl = "http://localhost:8083/dev/mythGadgetTest/";
                Settings.MythwebUrl = "http://localhost:8083/apps/mythweb";
                Settings.UpdateInterval = 5;
            }
#endif

            // Do an immediate update on start
            timer = Window.SetTimeout(new Callback(DoUpdate), 250);
        }

        private void OnSettingsClosed()
        {
			UpdateDockedState();
            DoUpdate();
        }

        private void DoUpdate()
        {
            if (!String.IsNullOrEmpty(Settings.StatusUrl))
            {
                DOMElement config = Document.GetElementById("config");
                config.ClassName = "set";

                if (!CallInProgress)
                {
                    CallInProgress = true;
                    MythtvStatus.GetStatus(new GetStatusCompletedCallback(StatusCompletedCallback));
                }
            }
            else
            {
                DOMElement config = Document.GetElementById("config");
                config.ClassName = "unset";
            }
        }

        private void SetWaitForUpdate()
        {
            if (timer != 0)
                Window.ClearInterval(timer);

            timer = Window.SetTimeout(new Callback(DoUpdate), Settings.UpdateInterval * 1000);
        }

        void StatusCompletedCallback(MythtvStatusResult result)
        {
            CallInProgress = false;
			
            AreaElement mythwebLink = (AreaElement)Document.GetElementById("mythweb");
            AreaElement upcomingLink = (AreaElement)Document.GetElementById("upcomingText");
            AreaElement guideText = (AreaElement)Document.GetElementById("guideText");
            if (!String.IsNullOrEmpty(Settings.MythwebUrl))
            {
                mythwebLink.Href = Settings.MythwebUrl;
                upcomingLink.Href = Settings.MythwebUrl + "tv/upcoming";
                guideText.Href = Settings.MythwebUrl + "tv/list";
            }
            else
            {
                mythwebLink.Href = "#";
                upcomingLink.Href = "";
                guideText.Href = "";
            }

			if (!result.Success || !result.ParseOk)
			{
				// Failed :-(
				DOMElement error = Document.GetElementById("error");
				error.ClassName = "error";
				error.InnerHTML = "Update Failed<br>" + result.DebugMessage;
			}
            else
            {
                DOMElement error = Document.GetElementById("error");
                error.ClassName = "ok";

                DOMElement dUpdated = Document.GetElementById("updated");
                dUpdated.InnerText = result.Updated.Format("HH:mm");

                DOMElement dEncoders = Document.GetElementById("encData");
                dEncoders.InnerHTML = string.Format("{0} idle, {1} busy", result.EncodersIdle, result.EncodersBusy);

                DOMElement dGuideDays = Document.GetElementById("guideDays");
                dGuideDays.InnerHTML = string.Format("{0} days", result.GuideDays);

                if (result.GuideDays < Settings.GuideWarningDays)
                    dGuideDays.ClassName = "warning";
                else
                    dGuideDays.ClassName = "";

                DOMElement dGuideResult = Document.GetElementById("guideResult");
                if (result.GuideStatus.Length > 12)
                    dGuideResult.InnerHTML = result.GuideStatus.Substring(0, 12);
                else
                    dGuideResult.InnerHTML = result.GuideStatus;

                if (result.GuideStatus != "Successful.")
                    dGuideResult.ClassName = "warning";
                else
                    dGuideResult.ClassName = "";

                DOMElement dDiskUsed = Document.GetElementById("diskUsed");
                dDiskUsed.InnerHTML = string.Format("{0}% used", result.DriveTotalUsedPercent);

                DOMElement dDiskFree = Document.GetElementById("diskFree");
                dDiskFree.InnerHTML = string.Format("({0}Gb Free)", result.DriveTotalFreeGb);

                DOMElement dUpcoming = Document.GetElementById("upcoming");
                dUpcoming.InnerHTML = "";
                for (int i = 0; i < result.Programs.Length; i++)
                {
                    dUpcoming.InnerHTML += string.Format
						(
						"{0}<br/><span class=\"ucSmall\">&nbsp;{1}{2}{3}</span><br/>", 
						result.Programs[i].Title, 
						result.Programs[i].ChannelCallSign, 
						Settings.DateOnNewLine ? "<br>&nbsp;" : ", ",
						result.Programs[i].StartTime.Format(Settings.DateFormat)
						);
                }
            }

            SetWaitForUpdate();
        }

        public static void Main(Dictionary arguments)
        {
            GadgetScriptlet scriptlet = new GadgetScriptlet();
        }

        private void OnFlyoutHide()
        {
            // TODO: Use Gadget.Flyout.Document to get to the HTML document within
            //       the Flyout page

            _flyoutVisible = false;
        }

        private void OnFlyoutShow()
        {
            _flyoutVisible = true;

            // TODO: Use Gadget.Flyout.Document to get to the HTML document within
            //       the Flyout page
        }

        private void OnUndock()
        {
            UpdateDockedState();
        }

        private void OnDock()
        {
            UpdateDockedState();
        }

        private void UpdateDockedState()
        {
            DOMElement body = Document.Body;

            if (Gadget.Docked)
            {
                Element.RemoveCSSClass(body, "undocked");
				Element.AddCSSClass(body, "docked");
            }
            else
            {
                Element.AddCSSClass(body, "undocked");
                Element.RemoveCSSClass(body, "docked");
            }

			body.Style.Height = Settings.GadgetHeight.ToString();
        }
    }
}
